package com.wbl.train.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wbl.train.business.service.TrainCarriageService;
import com.wbl.train.common.business.dto.DailyTrainCarriageDto;
import com.wbl.train.common.business.entity.*;
import com.wbl.train.business.mapper.DailyTrainCarriageMapper;
import com.wbl.train.business.service.DailyTrainCarriageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wbl.train.common.business.enums.SeatColEnum;
import com.wbl.train.common.exception.ApplicationException;
import com.wbl.train.common.page.PageVo;
import com.wbl.train.common.result.ResultCode;
import com.wbl.train.common.utils.SnowUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 每日车厢 服务实现类
 * @author 王博纶
 * @since 2024-02-11
 */
@AllArgsConstructor
@Slf4j
@Service
public class DailyTrainCarriageServiceImpl extends ServiceImpl<DailyTrainCarriageMapper, DailyTrainCarriageEntity> implements DailyTrainCarriageService {

    private final TrainCarriageService trainCarriageService;

    @Override
    public PageVo<DailyTrainCarriageEntity> queryTrainCarriage(DailyTrainCarriageDto dailyTrainCarriageDto) {
        // 获取分页所需要的参数
        int page = dailyTrainCarriageDto.getPage();
        int limit = dailyTrainCarriageDto.getLimit();

        LambdaQueryWrapper<DailyTrainCarriageEntity> trainCarriageWrapper = new LambdaQueryWrapper<DailyTrainCarriageEntity>()
                .orderByDesc(DailyTrainCarriageEntity::getDate) // 按照date降序排列
                .orderByAsc(DailyTrainCarriageEntity::getTrainCode) // 按照trainCode升序排列
                .orderByAsc(DailyTrainCarriageEntity::getCarriageIndex) // 按照carriageIndex升序排列
                // 根据date进行过滤，有值就过滤，没有值就不拼接条件
                .eq(ObjectUtil.isNotEmpty(dailyTrainCarriageDto.getDate()),DailyTrainCarriageEntity::getDate,dailyTrainCarriageDto.getDate())
                // 根据trainCode进行过滤，有值就过滤，没有值就不拼接条件
                .eq(ObjectUtil.isNotEmpty(dailyTrainCarriageDto.getTrainCode()),DailyTrainCarriageEntity::getTrainCode,dailyTrainCarriageDto.getTrainCode());
        //创建分页对象
        IPage<DailyTrainCarriageEntity> trainCarriagePage = new Page<>(page,limit);
        //调用分页方法
        IPage<DailyTrainCarriageEntity> trainCarriagePageData = page(trainCarriagePage,trainCarriageWrapper);
        // 获取查询出来的数据集合
        List<DailyTrainCarriageEntity> records = trainCarriagePageData.getRecords();
        // 将数据塞到PageVo类中并返回出去
        return new PageVo<DailyTrainCarriageEntity>()
                .setDataList(records)
                .setPageSize(limit).setCurrentPage(page)
                .setTotal((int) trainCarriagePageData.getTotal())
                .setPages((int) trainCarriagePageData.getPages());
    }

    @Override
    public boolean insertAndUpdateTrain(DailyTrainCarriageEntity dailyTrainCarriage) {
        // 获取当前的时间 --- 用于创建和修改的时候的时间填充
        DateTime now = DateTime.now();
        // 设置火车车站的修改时间
        dailyTrainCarriage.setUpdateTime(now);

        // 自动计算列数和总座位数
        List<SeatColEnum> seatCols = SeatColEnum.getColsByType(dailyTrainCarriage.getSeatType());
        dailyTrainCarriage
                // 设置列数 --- 列数为枚举类的长度
                .setColCount(seatCols.size())
                // 设置总座位数 --- 总座位数 = 列数 * 行数
                .setSeatCount(seatCols.size() * dailyTrainCarriage.getRowCount());
        // 判断Id是否为空
        if(ObjectUtil.isNotNull(dailyTrainCarriage.getId())){
            // 根据id查询火车车站信息
            DailyTrainCarriageEntity dailyTrainCarriageEntity = this.getById(dailyTrainCarriage.getId());
            // 当前id对应的无火车车站信息
            if(ObjectUtil.isNull(dailyTrainCarriageEntity)){
                throw new ApplicationException(ResultCode.DATA_NOT_EXIST,"当前火车车厢不存在");
            }
            // 更新火车车次信息
            return this.updateById(dailyTrainCarriage);
        }

        // 通过trainCode和carriageIndex进行火车车站信息的查询
        DailyTrainCarriageEntity dailyTrainCarriageEntity = getTrainCarriageByUniqueKey(dailyTrainCarriage.getDate(),dailyTrainCarriage.getTrainCode(),dailyTrainCarriage.getCarriageIndex());
        // 查询出的trainEntity不为空，不允许新增
        if(ObjectUtil.isNotEmpty(dailyTrainCarriageEntity)){
            throw new ApplicationException(ResultCode.DATA_EXIST,"当前火车车厢已存在");
        }
        // 给新增的火车车站设置Id，创建时间和修改时间
        dailyTrainCarriage.setId(SnowUtil.getSnowflakeNextId())
                .setCreateTime(now);
        // 新增火车车站
        return this.save(dailyTrainCarriage);
    }

    /**
     * 根据唯一键查询 trainCarriage 火车车厢信息
     * @param date 每日日期
     * @param trainCode 火车车次编号
     * @param carriageIndex 车厢序号
     * @return trainCarriage 火车车厢信息
     */
    private DailyTrainCarriageEntity getTrainCarriageByUniqueKey(LocalDate date,String trainCode, Integer carriageIndex) {
        LambdaQueryWrapper<DailyTrainCarriageEntity> wrapper = new LambdaQueryWrapper<DailyTrainCarriageEntity>()
                .eq(DailyTrainCarriageEntity::getDate,date)
                .eq(DailyTrainCarriageEntity::getTrainCode, trainCode)
                .eq(DailyTrainCarriageEntity::getCarriageIndex, carriageIndex);
        return this.getOne(wrapper);
    }

    public List<DailyTrainCarriageEntity> selectByTrainCode(String trainCode){
        LambdaQueryWrapper<DailyTrainCarriageEntity> wrapper = new LambdaQueryWrapper<DailyTrainCarriageEntity>()
                .eq(DailyTrainCarriageEntity::getTrainCode, trainCode)
                .orderByAsc(DailyTrainCarriageEntity::getCarriageIndex);
        return this.list(wrapper);
    }

    @Transactional
    public void genDailyCarriage(LocalDate date, String trainCode, Date now) {
        log.info("生成日期【{}】车次【{}】的车厢信息开始",date,trainCode);
        ArrayList<DailyTrainCarriageEntity> dailyTrainCarriageList = new ArrayList<>();
        // 删除某日某车次的车站信息
        LambdaUpdateWrapper<DailyTrainCarriageEntity> deleteWrapper = new LambdaUpdateWrapper<DailyTrainCarriageEntity>()
                .eq(DailyTrainCarriageEntity::getTrainCode, trainCode)
                .eq(DailyTrainCarriageEntity::getDate, date);
        this.remove(deleteWrapper);

        // 查出某车次的所有的车厢信息
        List<TrainCarriageEntity> trainCarriages = trainCarriageService.selectByTrainCode(trainCode);
        if(CollUtil.isEmpty(trainCarriages)){
            log.error("没有车厢基础数据，生成该车次车厢信息结束");
            throw new ApplicationException(ResultCode.DATA_NOT_EXIST,"没有车厢基础数据，生成该车次车厢信息结束");
        }

        for (TrainCarriageEntity trainCarriage : trainCarriages) {
            // 创建并添加 每日车次 信息
            dailyTrainCarriageList.add(BeanUtil.copyProperties(trainCarriage, DailyTrainCarriageEntity.class)
                    .setId(SnowUtil.getSnowflakeNextId())
                    .setDate(date)
                    .setCreateTime(now)
                    .setUpdateTime(now));
        }
        this.saveBatch(dailyTrainCarriageList);
        log.info("生成日期【{}】车次【{}】的车厢信息结束",date,trainCode);
    }

    @Override
    public List<DailyTrainCarriageEntity> selectBySeatType(LocalDate date, String trainCode, String seatType) {
        LambdaQueryWrapper<DailyTrainCarriageEntity> wrapper = new LambdaQueryWrapper<DailyTrainCarriageEntity>()
                .orderByAsc(DailyTrainCarriageEntity::getCarriageIndex) // 按照carriageIndex升序排列
                .eq(DailyTrainCarriageEntity::getDate,date)
                .eq(DailyTrainCarriageEntity::getTrainCode,trainCode)
                .eq(DailyTrainCarriageEntity::getSeatType,seatType);
        return this.list(wrapper);
    }
}
